﻿using System;
using System.Collections;
using System.Collections.Generic;
using Fwql.Net.Extensions;

namespace Fwql.Net.Utils
{
    /// <summary>
    /// 参数验证类
    /// </summary>
    public static class Guard
    {
        /// <summary>
        /// 确保参数值不为null
        /// </summary>
        /// <param name="param">参数值</param>
        /// <param name="paramName">参数名</param>
        public static void NotNull<T>(T param, string paramName)
        {
            if (param.IsNull())
            {
                throw new ArgumentNullException(paramName);
            }
        }

        /// <summary>
        /// 确保参数值不为null，也不为参数类型默认值，对Guid非常有用
        /// </summary>
        /// <param name="param">参数值</param>
        /// <param name="paramName">参数名</param>
        public static void NotDefault<T>(T param, string paramName)
        {
            NotNull(param, paramName);

            if (param.Equals(default(T)))
            {
                throw new ArgumentNullException(paramName);
            }
        }

        /// <summary>
        /// 确保参数集合不为null，也不为空
        /// </summary>
        /// <param name="param">参数值</param>
        /// <param name="paramName">参数名</param>
        public static void NotEmpty<T>(T param, string paramName) where T : IEnumerable
        {
            NotNull(param, paramName);
            if (!param.GetEnumerator().MoveNext())
            {
                throw new ArgumentNullException(paramName);
            }
        }

        /// <summary>
        /// 确保参数为有效的枚举值
        /// </summary>
        /// <param name="param">参数值</param>
        /// <param name="paramName">参数名</param>
        /// <typeparam name="TEnum">枚举类型</typeparam>
        public static void NotDefinedEnumValue<TEnum>(object param, string paramName)
        {
            if (!typeof (TEnum).IsEnum)
            {
                throw new NotSupportedException();
            }

            if (!Enum.IsDefined(typeof (TEnum), param))
            {
                throw new ArgumentOutOfRangeException(paramName);
            }
        }

        /// <summary>
        /// 确保参数值在指定范围之内
        /// </summary>
        /// <typeparam name="T">参数类型</typeparam>
        /// <param name="param">参数值</param>
        /// <param name="paramName">参数名</param>
        /// <param name="minValue">最小值</param>
        /// <param name="maxValue">最大值</param>
        /// <param name="includeBound">是否包括上下边界，默认包括</param>
        /// <param name="comparer"></param>
        public static void NotOutOfRange<T>(T param, string paramName, T minValue, T maxValue,
                                            bool includeBound = true, IComparer<T> comparer = null)
            where T : IComparable<T>
        {
            if (!param.IsBetween(minValue, maxValue, includeBound, comparer))
            {
                throw new ArgumentOutOfRangeException(paramName);
            }
        }

        /// <summary>
        /// 确保参数值大于指定值
        /// </summary>
        /// <typeparam name="T">参数类型</typeparam>
        /// <param name="param">参数值</param>
        /// <param name="paramName">参数名</param>
        /// <param name="minValue">最小值</param>
        /// <param name="includeEqual">是否包括等于，默认包括</param>
        /// <param name="comparer">比较器</param>
        public static void NotMaxWith<T>(T param, string paramName, T minValue, bool includeEqual = true,
                                         IComparer<T> comparer = null) where T : IComparable<T>
        {
            if (!param.IsMaxWith(minValue, includeEqual, comparer))
            {
                throw new ArgumentOutOfRangeException(paramName);
            }
        }

        /// <summary>
        /// 确保参数值小于指定值
        /// </summary>
        /// <typeparam name="T">参数类型</typeparam>
        /// <param name="param">参数值</param>
        /// <param name="paramName">参数名</param>
        /// <param name="maxValue">最大值</param>
        /// <param name="includeEqual">是否包括等于，默认包括</param>
        /// <param name="comparer">比较器</param>
        public static void NotMinWith<T>(T param, string paramName, T maxValue, bool includeEqual = true,
                                         IComparer<T> comparer = null) where T : IComparable<T>
        {
            if (!param.IsMinWith(maxValue, includeEqual, comparer))
            {
                throw new ArgumentOutOfRangeException(paramName);
            }
        }
    }

    class GuardObject<T>
    {
         
    }
}